/*
@author: ZZH
@date: 2021-11-04
@time: 09:55:46
@info: 各类操作的定义
*/
#pragma once
#define ARRAY_LENGTH(arr) (sizeof(arr) / sizeof(*arr))

#ifdef __OPT_DEBUG
#define DEBUG_OUTPUT printf
#else
#define DEBUG_OUTPUT(fmt, ...)
#endif

#define DEBUG_LEVEL(pre, level, fmt, ...) DEBUG_OUTPUT(pre "[" #level "]" fmt "\r\n", ##__VA_ARGS__)
#define RAW(fmt, ...) DEBUG_OUTPUT(fmt "\r\n", ##__VA_ARGS__)
#define LOG(fmt, ...) DEBUG_LEVEL("", log, ": " fmt, ##__VA_ARGS__)
#define INFO(fmt, ...) DEBUG_LEVEL("", info, "[%s]: " fmt, __func__, ##__VA_ARGS__)
#define WARNING(fmt, ...) DEBUG_LEVEL("\r\n", warning, "[%s:%d]: " fmt, __func__, __LINE__, ##__VA_ARGS__)
#define ERROR(fmt, ...) DEBUG_LEVEL("\r\n\r\n", error, "[%s:%d][%s]: " fmt "\r\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__)

#define FOR(index, num) for (unsigned int index = 0; index < num; index++) //指定变量循环num次
#define FOR_I(num) FOR(i, num)                                             //i变量循环num次
#define FOR_J(num) FOR(j, num)                                             //j变量循环num次
#define FOR_K(num) FOR(k, num)                                             //k变量循环num次

#define FOR_ARRAY(index, arr) FOR(index, ARRAY_LENGTH(arr)) //指定变量遍历数组下标
#define FOR_ARRAY_I(arr) FOR_ARRAY(i, arr)                  //i变量遍历数组下标
#define FOR_ARRAY_J(arr) FOR_ARRAY(j, arr)                  //j变量遍历数组下标
#define FOR_ARRAY_K(arr) FOR_ARRAY(k, arr)                  //k变量遍历数组下标

#define EACH(arr) for (typeof(*arr) *pMember = arr, *pEnd = arr + ARRAY_LENGTH(arr); pMember < pEnd; pMember ++) //this指针遍历数组

#define REG_UNION(strName, content) typedef union __##strName##_Typedef { struct content Fields; UINT32 Value; } strName##_TypeDef, *p##strName##_TypeDef
#define REG_STRUCT(strName, content) typedef struct __##strName##_Typedef content strName##_TypeDef, *p##strName##_TypeDef

#define FLOOR(x) ( (x) > (int)(x) ? (double)( (int)(x) ) : (double)((int)( (x)+1 )) )
#define CEIL(x) ( (x) < (int)(x) ? (double)( (int)(x) ) : (double)((int)( (x)+1 )) )

/*用于类型转换的结构体,可用指针将一段二进制数据以各种基本数据类型进行操作*/
REG_STRUCT(TypeCast, {
    union
 {
    /*signed basic types*/
    char ch;
    short sInteger;
    int integer;
    long lInteger;
    long long llInteger;
    float fNumber;
    double dNumber;


    /*unsigned basic types*/
    unsigned char uch;
    unsigned short usInteger;
    unsigned int uInteger;
    unsigned long ulInteger;
    unsigned long long ullInteger;


    /*const signed basic types*/
    const char cch;
    const short csInteger;
    const int cInteger;
    const long clInteger;
    const long long cllInteger;
    const float cfNumber;
    const double cdNumber;


    /*const unsigned basic types*/
    const unsigned char cuch;
    const unsigned short cusInteger;
    const unsigned int cuInteger;
    const unsigned long culInteger;
    const unsigned long long cullInteger;


    /*array of signed basic types*/
    char chArr[0];
    char string[0];//normally, array of char equals to a string
    short sIntegerArr[0];
    int integerArr[0];
    long lIntegerArr[0];
    long long llIntegerArr[0];
    float fNumberArr[0];
    double dNumberArr[0];


    /*array of unsigned basic types*/
    unsigned char uchArr[0];
    unsigned short usIntegerArr[0];
    unsigned int uintegerArr[0];
    unsigned long ulIntegerArr[0];
    unsigned long long ullIntegerArr[0];


    /*array of const signed basic types*/
    const char cchArr[0];
    const short csIntegerArr[0];
    const int cintegerArr[0];
    const long clIntegerArr[0];
    const long long cllIntegerArr[0];
    const float cfNumberArr[0];
    const double cdNumberArr[0];


    /*array of const unsigned basic types*/
    const unsigned char cuchArr[0];
    const unsigned short cusIntegerArr[0];
    const unsigned int cuintegerArr[0];
    const unsigned long culIntegerArr[0];
    const unsigned long long cullIntegerArr[0];


    /*it self*/
    struct __TypeCast_Typedef* pointTo;
};
});

//地址对齐
#define ALIGN_8 uint8_t
#define ALIGN_16 uint16_t
#define ALIGN_32 uint32_t

//LD脚本符号声明宏
#define LD_SYMBOL_ALIGN(sym, align) extern align sym[]
#define LD_SYMBOL(sym) LD_SYMBOL_ALIGN(sym, ALIGN_8)

//GNU属性宏
#define GNU_ATTRIBUTE(...) __attribute__((__VA_ARGS__))
#define GNU_SECTION(sn) GNU_ATTRIBUTE(section(sn))
#define GNU_ALIGN(ALG) GNU_ATTRIBUTE(aligned(ALG))
#define GNU_NORETURN GNU_ATTRIBUTE(noreturn)
#define GNU_UNUSED GNU_ATTRIBUTE(unused)
#define GNU_CONST GNU_ATTRIBUTE(const)
#define GNU_PURE GNU_ATTRIBUTE(pure)
#define GNU_WEAK GNU_ATTRIBUTE(weak)

//求结构体内某成员的偏移量
#ifndef offset_of
#define offset_of(type, member) ((size_t)&((type*)0)->member)
#endif

//已知结构体内某成员的地址和结构体类型,求结构体地址
#ifndef container_of
#define container_of(p, type, member) ((type*)((size_t)p - offset_of(type, member)))
#endif

//交换AB的变量值
#define SWAP(a, b) {typeof(a) __swap_var__ = a; a = b; b = __swap_var__;}
